(function(window,undefined){
    var Tools ={
        // 获取随机整数
        getRandom:function(min,max){
            min = Math.ceil(min);
            max = Math.floor(max);
            return Math.floor(Math.random() * (max - min + 1)) + min;
        },
        // 获取随机颜色
        getColor:function(){
            var r =this.getRandom(0,255);
            var g =this.getRandom(0,255);
            var b =this.getRandom(0,255);
            return "rgb("+ r + ","+g+","+b+")";    
        }
    }
    window.Tools = Tools;
})(window,undefined);
(function(window,undefined){
    // 将私有属性放到构造函数中
        function Food(option){
        // 确保option是属性值
        // option = option||{};
        // 使用三元表达式选择
        option = option instanceof Object? option:{};
        this.width = option.width||20;
        this.height = option.height||20;
        this.x = option.x || 0;
        this.y = option.y || 0;
        this.color = option.color||"yellow";
        this.arr = [];
        }
        var ps = "absolute";
    // 将一个元素渲染添加到页面上
        Food.prototype.render= function(stage){
        // 创建一个元素
        var ele = document.createElement("div");
    
        // 设置样式之前先获取随机的一个x和y
        this.x = Tools.getRandom(0,stage.clientWidth/this.width-1)*this.width;
        this.y = Tools.getRandom(0,stage.clientHeight/this.height-1)*this.height;
        
        // 给元素添加样式
        ele.style.width=this.width + "px";
        ele.style.height=this.height + "px";
        ele.style.left=this.x + "px";
        ele.style.top=this.y + "px"
        ele.style.backgroundColor=this.color;
        ele.style.position= ps;
        //将元素添加给父级
        stage.appendChild(ele);
        // 将元素添加给空的数组
        this.arr.push(ele);
        }
    // 删除父级内部的一个div元素
        Food.prototype.remove= function(stage,i){
        // 通过一些方法获取下标
    
        //  删除html结构中的div
        stage.removeChild(this.arr[i]);
        // 删除数组中的div
        this.arr.splice(i,1);
        }
        // 利用window对象暴露food,因此函数可以给外部使用
        window.Food = Food;
})(window,undefined);
(function(window,undefined){
    // 创建全局变量
    var ps = "absolute";
    // 创建一个构造函数，放置🐍的属性
    function Snake(option) {

    // 确定option是属性值  使用三元表达式选择
    option = option instanceof Object? option:{};
    // 确定蛇节的宽高属性
    this.width= option.width||20;
    this.height= option.height||20;
    // 确定蛇本身的属性（位置（x、y)，颜色，）及蛇移动的方向
    // 将多组自身属性值放在数组中
    this.body = [
        {x: 3,y: 2,color: "red"},
        {x: 2,y: 2,color: "blue"},
        {x: 1,y: 2,color: "blue"}
    ];
    // 蛇移动的方向 (top bottom left right)
    this.direction="right";
    // 创建一个新数组存储添加的元素
    this.arr = [];
    }
    // 添加一个元素渲染到页面上的方法
    Snake.prototype.render=function(stage){
        // 创建div元素,看数组情况生成对应个数的div
        // 循环遍历
        for(var i = 0, len=this.body.length;i<len;i++){
            // 每循环一次将body中的每一项(每一个对象)，存贮到一个变量中方便调取
            var piece=this.body[i];
            // 创建一个元素
            var ele = document.createElement("div");
            // 利用上述变量给元素添加样式
            ele.style.width=this.width + "px";
            ele.style.height=this.height + "px";
            ele.style.left=piece.x*this.width + "px";
            ele.style.top=piece.y*this.height + "px";
            ele.style.position=ps;
            ele.style.backgroundColor=piece.color;
            // 给父级添加这个元素
            stage.appendChild(ele);
            // 将数据存贮到空数组中
            this.arr.push(ele);
        }
    }
    // 让蛇开始运动的方法
    Snake.prototype.move=function(stage){
        // 蛇身每次运动时 后一个覆盖它的前面那一个
        // 利用for循环遍历，将每一个蛇身根据蛇的运动而变化
        // 定义开始之前的蛇身的长度
        // len=this.body.length
        for(var i = this.body.length-1;i>0;i--){
           this.body[i].x = this.body[i-1].x;
           this.body[i].y = this.body[i-1].y;  
        }
        // 定义蛇开始运动之前的蛇头位置
        var head= this.body[0];
        // 蛇头运动的方向的选择根据不同分支
        switch(this.direction){
            case "right":
                head.x +=1;
                break;
            case "left":
                head.x -=1;
                break;
            case "top":
                head.y -=1;
                break;
            case "bottom":
                head.y +=1;
                break;  
        }
    }
    // 删除前一次的蛇
    Snake.prototype.remove=function(stage){
    // 需要删除首先得有数据先存储数据(在前面的步骤中创建新元素并且村的数组中)
    // 删除html中的div(ele),ele的元素存在arr中，需要删除arr重的每一项
    for(var i = this.arr.length-1;i>=0;i--){
        stage.removeChild(this.arr[i]);
    }
    // 清空数组
    this.arr = [];
    }
    // 利用window对象暴露snake,因此函数可以给外部使用
    window.Snake = Snake;
})(window,undefined);
(function (window,undefined) {
    var that;
    // 创建一个游戏构造函数
    function Game(map) {
        // games 里面有三个属性（food，snakes，stage)
        // 用this.方法添加实例对象，window里面添加过构造函数Food
        // 利用window对象暴露过snake和food,因此函数可以给外部调用
        // 通过 window.new Food()方法来给this.赋值    this.food = new Food();
        this.food = new Food();
        this.snake = new Snake();
        this.stage = stage;
        that = this;
    }
    // 创建Game的构造函数的原型对象// 游戏开始的方法,方法内初始化food和snake
    Game.prototype.start = function () {
        // 将食物和蛇增加到stage上
        this.food.render(this.stage);
        this.food.render(this.stage);
        this.food.render(this.stage);
        this.snake.render(this.stage);
        runSnake();
    }

    // 让游戏开始
    // // 蛇开始运动给蛇的函数添加运动方法，game 拿来调用
    // this.snake.move(this.stage);
    // // 删除前一次渲染的蛇
    // this.snake.remove(this.stage);
    // // 再重新渲染
    // this.snake.render(this.stage);

    // 利用一个私有函数将蛇运动包装起来并且能获取构造函数里的属性和原型对象里的方法
    function runSnake() {
        // 1.让蛇自动运动（定时器作用下自动运动，判断范围是否停止）
        var timer = setInterval(function () {
            // 给蛇的函数添加运动   
            that.snake.move(that.stage);
            // 删除前一次渲染的蛇
            that.snake.remove(that.stage);
            // 再重新渲染
            that.snake.render(that.stage);

            // 判断是否吃到食物了（判断蛇是否与食物碰撞，如果碰撞增长自己的蛇节）
            // 如果蛇的位置与食物的位置相同就是碰撞

            // 获取食物的位置
            // var foodX= that.food.x;
            // var foodY= that.food.y;
            // 增加了食物个数之后,我们需要food 数组中的每一项的位置与蛇的位置比较
            for (var i = 0; i < that.food.arr.length; i++) {
                // 获取蛇的位置
                var hX = that.snake.body[0].x * that.snake.width;
                var hY = that.snake.body[0].y * that.snake.height;
                // 判断
                // if (foodX === hX && foodY === hY) {
                    if (that.food.arr[i].offsetLeft === hX  && that.food.arr[i].offsetTop === hY) {
                    // 如果碰撞
                    // 删除食物
                    that.food.remove(that.stage,i);
                    // 重新渲染一个新的食物
                    that.food.render(that.stage);
                    // 增长自己的蛇节 
                    // 获取body中的最后一项,在最后一项增加一项
                    var last = that.snake.body[that.snake.body.length - 1];
                    that.snake.body.push({
                        x: last.x,
                        y: last.y,
                        color: last.color
                    });
                    }
            }



            // 每次把上述三步执行完就判断一次是否超过范围
            // 定义最大份数
            var maxX = that.stage.offsetWidth / that.snake.width;
            var maxY = that.stage.offsetHeight / that.snake.height;
            // 获得蛇头当前位置
            var headX = that.snake.body[0].x;
            var headY = that.snake.body[0].y;
            if (headX < 0 || headX >= maxX || headY < 0 || headY >= maxY) {
                clearInterval(timer);
                alert("Game over");
            }
        }, 150);
    }
    // 2.蛇根据上下左右按键换方向
    bindkey();
    function bindkey() {
        document.onkeydown = function (e) {
            // console.log(e.keyCode);
            switch (e.keyCode) {
                case 37:
                    that.snake.direction = "left";
                    break;
                case 38:
                    that.snake.direction = "top";
                    break;
                case 39:
                    that.snake.direction = "right";
                    break;
                case 40:
                    that.snake.direction = "bottom";
                    break;

            }
        }
    }
    // 3.蛇与食物是否碰撞
    // 4.是否超出范围


    window.Game = Game;
})(window,undefined);
(function(window,undefined){
    // 获取元素
    var stage = document.getElementById("stage");
    // // 生成实例
    var game = new Game(stage);
    // // 调用实例 
    game.start();
})(window,undefined);